package com.shire.shire_interface.service.commandcenter;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONArray;
import com.shire.shire_interface.constants.WxConstants;
import com.shire.shire_interface.constants.WxConstants.CmdType;
import com.shire.shire_interface.constants.WxErrorCode;
import com.shire.shire_interface.dao.accounts.WxAccountDao;
import com.shire.shire_interface.model.command.WxCommand;
import com.shire.shire_interface.model.user.WxAccount;
import com.shire.shire_interface.model.user.WxAccountExample;
import com.shire.shire_interface.service.account.WxAccountService;
import com.shire.shire_interface.service.chat.WxChatService;
import com.shire.shire_interface.service.friend.WxFriendLogService;
import com.shire.shire_interface.service.group.impl.WxGroupInviteService;
import com.shire.shire_interface.service.invite.WxInviteSubTaskService;
import com.shire.shire_interface.service.marketing.WxGroupTaskService;
import com.shire.shire_interface.service.massmsg.WxMassMsgItemService;
import com.shire.shire_interface.service.timeline.WxFriendTimelineService;
import com.shire.shire_interface.service.timeline.WxTimelineTaskService;
import com.shire.shire_interface.service.validation.WxValidationRecordService;
import com.shire.shire_interface.service.validation.WxValidationRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.shire.shire_interface.constants.WxConstants.CmdType.get;

@Component
public class BaseCommandProcessor {
    private Map<Integer,CSCommandStore> commandStoreMap;

    @Autowired
    private WxAccountDao accountDao;

    @Resource
    private CSCommandStore commandStore;

    @Resource
    private WxCommandService commandService;

    @Resource
    private WxChatService chatService;
    @Resource
    private WxGroupInviteService wxGroupInviteService;
    @Resource
    private WxFriendLogService friendLogService;
    @Resource
    private WxTimelineTaskService timelineTaskService;
    @Resource
    private WxFriendTimelineService timelineService;
    @Resource
    private WxGroupTaskService groupTaskService;
    @Resource
    private WxValidationRecordService validationRecordService;
    @Resource
    private WxValidationRuleService validationRuleService;
    @Resource
    private WxAccountService accountService;
    @Resource
    private WxMassMsgItemService massMsgItemService;
    @Resource
    private WxInviteSubTaskService inviteSubTaskService;


    public BaseCommandProcessor() {
        commandStoreMap = new HashMap<>();
    }

    //初始化指令处理器，加裁所有待执行命令
    @PostConstruct
    private void loadCommand() {
        Map accountMap = new HashMap();
        accountMap.put("accountStatus", WxConstants.AccountStatus.ENABLE.getCode());
        WxAccountExample example = new WxAccountExample();
        example.createCriteria().andAccountstatusEqualTo(WxConstants.AccountStatus.ENABLE.getCode());
        List<WxAccount> accounts = accountDao.selectByExample(example);

        for (WxAccount account : accounts) {
//            if (account.getCsid() == null)
//                continue; //尚未分配客服
            addAccount(account);
        }
    }


    public void addAccount(WxAccount account) {
        CSCommandStore store = commandStore.getCommandStoreForAccount(account);
        commandStoreMap.put(account.getId(), store);
    }

    public void sendSyncAddressToAll() {
        for (Integer storeKey : commandStoreMap.keySet()) {
            CSCommandStore store = commandStoreMap.get(storeKey);
            store.addCommand(commandService.genSyncAddressCmd(store.getCsAccount()));
        }
    }

    public WxCommand getCommandForCS(Integer csId, Integer wxAccount) {

        CSCommandStore store = commandStoreMap.get(wxAccount);
        if (store == null)
            return null;
        return store.getNextCommand();
    }

    public void addCommand(Integer csId, Integer accountId, WxCommand command) {
        if (!commandStoreMap.containsKey(accountId)) {
            addAccount(accountDao.selectByPrimaryKey(accountId));
        }
        commandStoreMap.get(accountId).addCommand(command);
    }


    public void responseCommand(Integer csId, Integer accountId, WxCommand cmd){
        commandStoreMap.get(accountId).responseCommand(cmd);
    }

    public void retryCommand(){
        for (CSCommandStore csCommandStore : commandStoreMap.values()) {
            csCommandStore.retryCommands();
        }
    }


    public void checkOverTimeCmd() {
        for (CSCommandStore csCommandStore : commandStoreMap.values()) {
            List<WxCommand> cmdList = csCommandStore.getOvertimeCommand();
            for (WxCommand command : cmdList) {
                command.setRststatus(WxErrorCode.CMD_TIMEOUT);
                Map<String, Object> respContent = new HashMap<>();
                command.setRespcontent(JSONUtils.toJSONString(respContent));
                command.setCmdstatus(WxConstants.CmdStatus.TIMEOUT.getCode());
                command.setUpdatetime(new Date());
                commandService.updateWxCommand(command);

                CmdType cmdType = get(command.getCmdtype());
                switch (cmdType) {
                    case CRK_SEND_CHAT:
                    case CRK_SEND_CHAT_D:
                    case CRK_SCAN_IMAGE:
                    case CRK_ACCEPT_CARD:
                    case CRK_SEND_CHAT_D_FILE:
                    case CRK_SEND_CHAT_D_IMAGE:
                    case CRK_SEND_CHAT_D_NAMECARD:
                    case CRK_SEND_CHAT_D_VIDEO:
                    case CRK_SEND_CHAT_D_LINK:
                        chatService.respSendChat(command, respContent);
                        break;
                    case CRK_JOIN_GROUP:
                        //chatService.respJoinGroup(wxCommand);
                        break;
                    case CRK_INVITE_GROUP:
                        wxGroupInviteService.respInviteGroup(command);
                        break;
                    case CRK_ADD_FRIEND:
                        break;
                    case CRK_ADD_WXID:
                        friendLogService.updateFriendLogByCmd(command);
                        break;
                    case CRK_SEND_LINK:
//                    wxAdItemService.respSendAdItem(wxCommand);
                        break;
                    case CRK_QUIT_GROUP:
//                    wxGroupService.respQuitGroup(wxCommand);
                        break;
                    case CRK_SEND_TIMELINE_LINK_D:
                    case CRK_SEND_TIMELINE_IMAGE_D:
                    case CRK_SEND_TIMELINE_VIDEO_D:
                    case CRK_SEND_TIMELINE_TEXT_D:
                        timelineTaskService.updateTimelineTaskByCommand(command);
                        break;
                    case CRK_CREATE_GROUP_D:
                        groupTaskService.updateGroupTaskItemByCmdId(command, respContent);
                        break;
                    case CRK_HELLO_VERIFY_D:
                        validationRecordService.updateRecordByCmd(command);
                        validationRuleService.syncValidationList(command.getCsid(), command.getAccountid());
                        break;
                    case CRK_HELLO_FETCH_D:
                        if (respContent.containsKey("hellos"))
                            validationRecordService.syncValidationForAccount(accountService.getWxAccountById(command.getAccountid()), JSONArray.parseArray(JSONUtils.toJSONString(respContent.get("hellos"))));
                        break;
                    case CRK_UPDATE_PROFILE:
                        accountService.accountUpdated(command);
                        break;
                    default:
                        break;
                }

                WxConstants.CmdTaskType taskType = WxConstants.CmdTaskType.get(command.getTasktype());
                switch (taskType) {
                    case UNKNOWN:
                        break;
                    case INVITE:
                        inviteSubTaskService.updateSubTaskRststatus(command.getTaskid(), command.getRststatus());
                        break;
                    case MASSMSG:
                        massMsgItemService.updateItem(command.getTaskid(), command.getRststatus());
                        break;
                    default:
                        break;

                }
            }
        }
    }
}
